# This is file is used to import emails from Mbox file

import fileinput #to read a big file 
from emailClass import *
import chardet
from couchdbkit import *
import time
import threading
import os
import mailbox

ENCODINGS = {'EUC-TW': 'big5'}

def to_unicode(s, verbose=False):
    # try to decode the a string
    if isinstance(s, unicode):
        return s
    if not s:
        return u''
  
    guess = chardet.detect(s)
    logging.debug('Detected encoding %s (conf: %s)', guess['encoding'], guess['confidence'])
    enc = ENCODINGS.get(guess['encoding'], guess['encoding'])

    try:
        u = unicode(s, enc)
    except UnicodeDecodeError, err:
        u = to_unicode_by_line(s, enc)
    return u

def to_unicode_by_line(s, encoding):
  decoded_lines = []

  for line in s.splitlines():
    if not line:
      decoded_lines.append(u'')
      continue

    try:
      u = unicode(line, encoding)
    except UnicodeDecodeError, err:
      logging.error('Could not decode %s', line)
      u = line.decode(encoding,'ignore')
    decoded_lines.append(u)
          
  return '\n'.join(decoded_lines)

def importMbox2(mbox, mailinglist):
    # DO NOT USE THIS
    # return a list of Emails object 
    # mbox is an mbox file (filename),
    # mailinglist is the name of the mailing list
    counter = 0
    emailList = []
    mail = EmailCreator(mailinglist)
    text = ""
    endEaders = False
    # read file line by line
    oldline = ""
    for line in fileinput.input(mbox):
        if(line.startswith("From ") and (oldline=="\n" or oldline=="")): # new email
            mail.addText(text)
            emailList.append(mail)
            counter += 1
            #if counter%10 == 0:
            #    sys.stdout.write('.')
            #    sys.stdout.flush()
            mail = EmailCreator(mailinglist)
            text = ""
            endEaders = False
        elif (line == "\n" or line == ""): #end of headers or end message
            if(endEaders):
                #text = text + "\n" + to_unicode(line)
                text = text + "\n" + line.decode('utf-8', 'ignore')
            else:
                endEaders = True
        else:
            if(endEaders):
                #text = text + "\n" + to_unicode(line)
                text = text + "\n" + line.decode('utf-8', 'ignore')
            else:
                #mail.addHeader(to_unicode(line))
                mail.addHeader(line.decode('utf-8', 'ignore'))
        oldline = line
    # append last email
    emailList.append(mail)
    return emailList

def importMbox(mbox_file, mailingList):
    # return a list of Emails object 
    # mbox is an mbox file (filename),
    # mailinglist is the name of the mailing list
    mbox_emails = mailbox.mbox(mbox_file)
    print mailingList
    emailList = []
    # return  [Email().creator(mbox_email, mailingList) for mbox_email in mbox_emails]
    for mbox_email in mbox_emails:
        email = Email().creator(mbox_email, mailingList)
        if email: #check if the email is not None
            emailList.append(email)
    return emailList
            
            

def chunks(l, n):
    """ Yield successive n-sized chunks from l.
    """
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

class MBoxImporter:
    mailRead = 0 # number of emails read form mbox file

    def __init__(self, mailinglist, filename, couchdbServer, databaseName):
        self.mailinglist = mailinglist
        self.filename = filename
        self.couchdbServer = couchdbServer
        self.databaseName = databaseName

    def saveInDatabase(self):
        # read an mbox file and save to the database
        # return number of email read and stored and time needed
        start = time.clock()
        elist = importMbox(self.filename, self.mailinglist)
        end = time.clock()
        self.mailRead = len(elist) 
        server = Server(self.couchdbServer)
        db = server.get_or_create_db(self.databaseName)
        startdb = time.clock()
#        for e in elist:
#            
#            if not(e.date is None):
#                ex = e.commitToDatabase(server, db)
#                if ex:
#                    self.mailInDB += 1
#                if(self.mailInDB%100 == 0):
#                    sys.stdout.write('.')
#                    sys.stdout.flush()
#            else:
#                self.mailNoneDate +=1
        for emails_chunk in chunks(elist, 50):
            try:
                db.save_docs(emails_chunk)
            except: 
                # error while importing: re-import one-by-one
                print "Error while importing"
                imp = 0
                for email in emails_chunk:
                    ex= email.commitToDatabase(server, db) 
                    if ex:
                        imp += 1
                sys.stdout.write(str(imp)+"\n")
            sys.stdout.write('.')
            sys.stdout.flush()
        enddb = time.clock()
        return self.mailRead, end-start, enddb-startdb
        
class MainThread(threading.Thread):
    # thread used to import emails from an mbox file
    def __init__(self, mailinglist, filename, couchdbServer, databaseName):
        threading.Thread.__init__(self)
        self.mailinglist = mailinglist
        self.filename = filename
        self.couchdbServer = couchdbServer
        self.databaseName = databaseName
        
    def run(self):
        print "Importing emails thread start"
        #importer = MBoxImporter(maillist, '/tmp/'+str(rand)+datafile.filename, couchdb, database)
        importer = MBoxImporter(self.mailinglist, self.filename, self.couchdbServer, self.databaseName)
        r,tread,tdb = importer.saveInDatabase()
        #remove tmp file
        os.remove(self.filename)   
        print "\n Mail read = " +str(r) + "\n time to read: "+str(tread)+"\n time to save in database: "+str(tdb)
             
#test
#im = MBoxImporter("mina-dev", "test/mina-dev.mbox", "http://localhost:5984", "test")
#im.saveInDatabase()
